package br.mikhas.db.model;

import java.io.Serializable;
import java.util.Collection;
import java.util.Collections;

import br.mikhas.db.util.ReflectionUtils;

/**
 * Defines the storage model for a java class.
 * 
 * @author Mikhail Domanoski
 * 
 */
public class Model {

	/**
	 * The current model version
	 */
	public static final int CURRENT_MODEL_VERSION = 1;

	/**
	 * The minimum model version
	 */
	public static final int MIN_MODEL_VERSION = 1;

	/**
	 * The maximum model version
	 */
	public static final int MAX_MODEL_VERSION = 1;

	/**
	 * The model's fields
	 */
	protected Collection<Field> fields;

	/**
	 * The name of the class which this model represents
	 */
	protected String className;

	/**
	 * The class which this model represents
	 */
	protected Class<? extends Serializable> modelClass;

	/**
	 * The serial version of the class
	 */
	protected long classSerial;

	/**
	 * The model index
	 */
	protected Index index;

	/**
	 * The model length in bytes
	 */
	protected int length;

	/**
	 * Gets the model fields
	 * 
	 * @return
	 */
	public Collection<Field> getFields() {
		return Collections.unmodifiableCollection(this.fields);
	}

	/**
	 * Get the name of the class which this model represents
	 * 
	 * @return the className
	 */
	public String getClassName() {
		return this.className;
	}

	/**
	 * Checks if this model accepts
	 * 
	 * @param cls
	 * @return true if this model accepts this version of the class
	 */
	public boolean acceptClassVersion(Class<? extends Serializable> cls) {
		if (modelClass.isAssignableFrom(cls)) {

			long serial = ReflectionUtils.getClassSerial(cls);
			return serial == this.classSerial;

		} else {
			return false;
		}
	}

	/**
	 * Gets the model version according to the API version
	 * 
	 * @return the modelVersion
	 */
	public int getModelVersion() {
		return CURRENT_MODEL_VERSION;
	}

	@Override
	public String toString() {
		return "Model[class=" + className + ";serial=" + classSerial + ']';

	}

	/**
	 * Return the model length in bytes
	 * 
	 * @return
	 */
	public int getLength() {
		return this.length;
	}

	/**
	 * Gets the model's index
	 * 
	 * @return
	 */
	public Index getIndex() {
		return this.index;
	}
}
